package com.duoec.dw.lineage.service.analyser.from;

import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.duoec.dw.lineage.dto.*;
import com.duoec.dw.lineage.exceptions.LineageAnalyseException;
import com.duoec.dw.lineage.service.LineageTableService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.LinkedHashSet;

/**
 * @author xuwenzhen
 */
@Service
public class ExprTableSourceAnalyser extends BaseTableSourceAnalyser<SQLExprTableSource> {
    private static final Logger logger = LoggerFactory.getLogger(ExprTableSourceAnalyser.class);

    @Autowired
    private LineageTableService lineageTableService;

    /**
     * 获取当前类处理的类型
     *
     * @return SQLTableSource子类类型
     */
    @Override
    public Class<SQLExprTableSource> getTableSourceType() {
        return SQLExprTableSource.class;
    }

    /**
     * 解析 from
     *
     * @param tableSource         需要解析的from
     * @param withAsTableLineages with-in
     * @return 当前select脚本的血缘关系
     */
    @Override
    public MultiTableLineageDto analyse(SQLExprTableSource tableSource, MultiTableLineageDto withAsTableLineages) {
        MultiTableLineageDto multiTableLineageDto = new MultiTableLineageDto();
        TableLineageDto dto = new TableLineageDto();
        SQLExpr expr = tableSource.getExpr();
        if (expr instanceof SQLPropertyExpr) {
            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;
            dto.setTableName(propertyExpr.getName());

            SQLExpr owner = propertyExpr.getOwner();
            if (owner instanceof SQLPropertyExpr) {
                //如果指定了数据源时，当前owner会带数据源的名称！
                dto.setDatabaseName(((SQLPropertyExpr) owner).getName());
            } else {
                dto.setDatabaseName(owner.toString());
            }

            //从表中加载实际的字段
            setTableFields(dto);
        } else if (expr instanceof SQLIdentifierExpr) {
            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;
            String tableName = identifierExpr.getName();
            if (withAsTableLineages != null) {
                TableLineageDto withAsTable = withAsTableLineages.get(tableName);
                if (withAsTable != null) {
                    //浅复制
                    BeanUtils.copyProperties(withAsTable, dto);
                }
            } else {
                dto.setTableName(tableName);
            }
        } else {
            throw new LineageAnalyseException("未实现类[" + expr.getClass().getName() + "]的解析！");
        }
        dto.setAlias(tableSource.getAlias());
        multiTableLineageDto.add(dto);
        return multiTableLineageDto;
    }

    private void setTableFields(TableLineageDto dto) {
        TableInfoDto table = lineageTableService.getTableDto(dto);
        if (table == null) {
            //TODO
            logger.warn("无法加载表字段信息：{}.{}", dto.getDatabaseName(), dto.getTableName());
            return;
        }
        LinkedHashSet<TableFieldLineageDto> fields = dto.getFields();
        if (fields == null) {
            fields = new LinkedHashSet<>();
            dto.setFields(fields);
        }
        for (TableFieldDto field : table.getFields()) {
            TableFieldLineageDto f = new TableFieldLineageDto();
            f.setIndex(fields.size());
            f.setColName(field.getColName());
            fields.add(f);
        }
    }

    public void setLineageTableService(LineageTableService lineageTableService) {
        this.lineageTableService = lineageTableService;
    }
}
